﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.Extensions.DependencyInjection;

namespace Marmat.FrameWork
{
    /// <summary>
    /// 服务工厂
    /// </summary>
    internal static class ServiceCollectionFactory
    {
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private static IServiceProvider serviceProvider;

        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private static IServiceCollection serviceCollection;

        /// <summary>
        /// 获取工厂提供的服务容器。
        /// </summary>
        /// <returns></returns>
        internal static IServiceCollection GetServiceCollection()
        {
            return ServiceCollectionFactory.serviceCollection;
        }



        /// <summary>
        /// 获取工厂提供的服务容器。
        /// </summary>
        /// <returns></returns>
        internal static IServiceProvider GetServiceProvider()
        {
            return ServiceCollectionFactory.serviceProvider;
        }

        /// <summary>
        /// 创建一个Microsoft.Extensions.DependencyInjection.ServiceProvider。
        /// </summary>
        /// <returns></returns>
        internal static IServiceProvider BuildServiceProvider()
        {
            return ServiceCollectionFactory.serviceCollection.BuildServiceProvider();
        }

        /// <summary>
        /// 设置服务提供者
        /// </summary>
        /// <param name="serviceCollection"></param>
        internal static void SetServiceCollection(IServiceCollection serviceCollection)
        {
            ServiceCollectionFactory.serviceCollection = serviceCollection;
        }

        /// <summary>
        /// 设置服务提供者
        /// </summary>
        /// <param name="serviceProvider"></param>
        internal static void SetServiceProvider(System.IServiceProvider serviceProvider)
        {
            ServiceCollectionFactory.serviceProvider = serviceProvider;
        }

        /// <summary>
        /// 将serviceType中指定的类型的单例服务添加到指定的IServiceCollection。
        /// </summary>
        /// <param name="serviceType">要注册的服务类型。</param>
        /// <param name="implementationType">服务的实现类型。</param>
        internal static void AddSingleton(Type serviceType, Type implementationType)
        {
            serviceCollection.AddSingleton(serviceType, implementationType);
        }

        /// <summary>
        /// 使用实现添加TService中指定类型的单例服务。
        /// </summary>
        /// <typeparam name="TService">要添加的服务类型。</typeparam>
        /// <typeparam name="TImplementation">要使用的实现类型。</typeparam>
        /// <returns></returns>
        internal static void AddSingleton<TService, TImplementation>() where TService : class where TImplementation : class, TService
        {
            serviceCollection.AddSingleton<TService, TImplementation>();
        }


        /// <summary>
        /// 使用实现添加serviceType中指定的类型的限定范围的服务
        /// </summary>
        /// <param name="serviceType">要注册的服务类型。</param>
        /// <param name="implementationType">服务的实现类型。</param>
        internal static void AddScoped(Type serviceType, Type implementationType)
        {
            serviceCollection.AddScoped(serviceType, implementationType);
        }

        /// <summary>
        /// 使用实现添加serviceType中指定的类型的限定范围的服务。
        /// </summary>
        /// <typeparam name="TService">要添加的服务类型。</typeparam>
        /// <typeparam name="TImplementation">要使用的实现类型。</typeparam>
        /// <returns></returns>
        internal static void AddScoped<TService, TImplementation>() where TService : class where TImplementation : class, TService
        {
            serviceCollection.AddScoped<TService, TImplementation>();
        }

        /// <summary>
        /// 使用实现添加serviceType中指定的类型的临时服务。
        /// </summary>
        /// <param name="serviceType">要注册的服务类型。</param>
        /// <param name="implementationType">服务的实现类型。</param>
        internal static void AddTransient(Type serviceType, Type implementationType)
        {
            serviceCollection.AddTransient(serviceType, implementationType);
        }

        /// <summary>
        /// 使用实现添加serviceType中指定的类型的临时服务。
        /// </summary>
        /// <typeparam name="TService">要添加的服务类型。</typeparam>
        /// <typeparam name="TImplementation">要使用的实现类型。</typeparam>
        /// <returns></returns>
        internal static void AddTransient<TService, TImplementation>() where TService : class where TImplementation : class, TService
        {
            serviceCollection.AddTransient<TService, TImplementation>();
        }

        /// <summary>
        /// 通过依赖注入获取T类型的服务。
        /// </summary>
        /// <param name="serviceType">需要获取的类型</param>
        /// <returns></returns>
        internal static object GetService(Type serviceType)
        {
            if (ServiceCollectionFactory.serviceProvider is null)
                throw new NullReferenceException();
            return serviceProvider.GetService(serviceType);
        }

        /// <summary>
        /// 通过依赖注入获取T类型的服务的集合。
        /// </summary>
        /// <param name="serviceType">需要获取的类型</param>
        /// <returns></returns>
        internal static IEnumerable<object> GetServices(Type serviceType)
        {
            if (ServiceCollectionFactory.serviceProvider is null)
                throw new NullReferenceException();
            return serviceProvider.GetServices(serviceType);
        }

        /// <summary>
        /// 通过依赖注入获取T类型的服务。
        /// </summary>
        /// <typeparam name="T">需要获取的类型</typeparam>
        /// <returns></returns>
        internal static T GetService<T>() where T : class
        {
            if (ServiceCollectionFactory.serviceProvider is null)
                throw new NullReferenceException();
            return serviceProvider.GetService<T>();
        }

        /// <summary>
        /// 通过依赖注入获取T类型的服务的集合。
        /// </summary>
        /// <typeparam name="T">需要获取的类型</typeparam>
        /// <returns></returns>
        internal static IEnumerable<T> GetServices<T>() where T : class
        {
            if (ServiceCollectionFactory.serviceProvider is null)
                throw new NullReferenceException();
            return serviceProvider.GetServices<T>();
        }
    }
}
